using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Services;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Uow;
using TenantManagementService.Monitoring;

namespace TenantManagementService.Monitoring
{
    /// <summary>
    /// 告警通知服务
    /// </summary>
    public class AlertNotificationService : DomainService
    {
        private readonly IRepository<Alert, Guid> _alertRepository;
        private readonly IRepository<AlertRule, Guid> _alertRuleRepository;
        private readonly IDistributedEventBus _distributedEventBus;
        private readonly ILogger<AlertNotificationService> _logger;

        public AlertNotificationService(
            IRepository<Alert, Guid> alertRepository,
            IRepository<AlertRule, Guid> alertRuleRepository,
            IDistributedEventBus distributedEventBus,
            ILogger<AlertNotificationService> logger)
        {
            _alertRepository = alertRepository;
            _alertRuleRepository = alertRuleRepository;
            _distributedEventBus = distributedEventBus;
            _logger = logger;
        }

        /// <summary>
        /// 发送告警通知
        /// </summary>
        [UnitOfWork]
        public async Task SendAlertNotificationAsync(Guid alertId)
        {
            try
            {
                var alert = await _alertRepository.GetAsync(alertId);
                if (alert.Status != AlertStatus.Active)
                {
                    _logger.LogDebug("告警 {AlertId} 状态不是活跃状态，跳过通知", alertId);
                    return;
                }

                // 检查是否需要通知
                if (!alert.NeedsRenotification())
                {
                    _logger.LogDebug("告警 {AlertId} 在通知间隔内，跳过重复通知", alertId);
                    return;
                }

                var alertRule = await _alertRuleRepository.GetAsync(alert.AlertRuleId);
                var notificationChannels = alertRule.GetNotificationChannels();

                if (notificationChannels == null || notificationChannels.Count == 0)
                {
                    _logger.LogDebug("告警规则 {RuleName} 没有配置通知渠道", alertRule.DisplayName);
                    return;
                }

                // 发布告警事件
                await PublishAlertEventAsync(alert, alertRule, notificationChannels);

                // 标记为已通知
                alert.MarkAsNotified();
                await _alertRepository.UpdateAsync(alert);

                _logger.LogInformation("告警通知已发送: {AlertTitle} - 通知渠道: {Channels}",
                    alert.Title, string.Join(", ", notificationChannels));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送告警通知失败: {AlertId}", alertId);
            }
        }

        /// <summary>
        /// 批量发送告警通知
        /// </summary>
        [UnitOfWork]
        public async Task SendBatchAlertNotificationsAsync(List<Guid> alertIds)
        {
            if (alertIds == null || alertIds.Count == 0)
            {
                return;
            }

            foreach (var alertId in alertIds)
            {
                await SendAlertNotificationAsync(alertId);
            }
        }

        /// <summary>
        /// 发送活跃告警汇总通知
        /// </summary>
        [UnitOfWork]
        public async Task SendActiveAlertsSummaryAsync(Guid? tenantId = null)
        {
            try
            {
                var queryable = await _alertRepository.GetQueryableAsync();
                queryable = queryable.Where(a => a.Status == AlertStatus.Active);

                if (tenantId.HasValue)
                {
                    queryable = queryable.Where(a => a.TenantId == tenantId.Value);
                }

                var activeAlerts = await AsyncExecuter.ToListAsync(queryable);

                if (activeAlerts.Count == 0)
                {
                    _logger.LogDebug("没有活跃告警，跳过汇总通知");
                    return;
                }

                // 按严重级别分组统计
                var alertsByLevel = activeAlerts.GroupBy(a => a.Level)
                    .ToDictionary(g => g.Key, g => g.Count());

                var summary = new ActiveAlertsSummary
                {
                    TotalCount = activeAlerts.Count,
                    AlertsByLevel = alertsByLevel,
                    TenantId = tenantId,
                    CreatedAt = DateTime.Now
                };

                // 发布告警汇总事件
                await _distributedEventBus.PublishAsync(new AlertSummaryEto
                {
                    SummaryId = Guid.NewGuid(),
                    TenantId = tenantId,
                    TotalAlerts = summary.TotalCount,
                    CriticalAlerts = alertsByLevel.GetValueOrDefault(AlertLevel.Critical, 0),
                    EmergencyAlerts = alertsByLevel.GetValueOrDefault(AlertLevel.Emergency, 0),
                    WarningAlerts = alertsByLevel.GetValueOrDefault(AlertLevel.Warning, 0),
                    InfoAlerts = alertsByLevel.GetValueOrDefault(AlertLevel.Info, 0),
                    CreatedAt = summary.CreatedAt
                });

                _logger.LogInformation("活跃告警汇总通知已发送: 总计 {TotalCount} 个告警", summary.TotalCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送活跃告警汇总通知失败");
            }
        }

        /// <summary>
        /// 处理告警解决通知
        /// </summary>
        [UnitOfWork]
        public async Task SendAlertResolvedNotificationAsync(Guid alertId)
        {
            try
            {
                var alert = await _alertRepository.GetAsync(alertId);
                if (alert.Status != AlertStatus.Resolved)
                {
                    return;
                }

                var alertRule = await _alertRuleRepository.GetAsync(alert.AlertRuleId);
                var notificationChannels = alertRule.GetNotificationChannels();

                if (notificationChannels == null || notificationChannels.Count == 0)
                {
                    return;
                }

                // 发布告警解决事件
                await _distributedEventBus.PublishAsync(new AlertResolvedEto
                {
                    AlertId = alert.Id,
                    TenantId = alert.TenantId,
                    AlertTitle = alert.Title,
                    AlertLevel = alert.Level,
                    Duration = alert.Duration,
                    HandledBy = alert.Assignee,
                    HandleNote = alert.HandleNote,
                    ResolvedAt = alert.EndTime ?? DateTime.Now
                });

                _logger.LogInformation("告警解决通知已发送: {AlertTitle}", alert.Title);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送告警解决通知失败: {AlertId}", alertId);
            }
        }

        /// <summary>
        /// 发送告警阈值接近通知
        /// </summary>
        [UnitOfWork]
        public async Task SendThresholdWarningNotificationsAsync()
        {
            try
            {
                // 获取接近阈值的告警（80%-95%）
                var queryable = await _alertRepository.GetQueryableAsync();
                queryable = queryable.Where(a => a.Status == AlertStatus.Active &&
                    a.Level >= AlertLevel.Warning &&
                    a.Level <= AlertLevel.Critical);

                var warningAlerts = await AsyncExecuter.ToListAsync(queryable);

                foreach (var alert in warningAlerts)
                {
                    await SendThresholdWarningNotificationAsync(alert);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送阈值警告通知失败");
            }
        }

        private async Task PublishAlertEventAsync(Alert alert, AlertRule alertRule, List<string> channels)
        {
            var alertEto = new AlertTriggeredEto
            {
                AlertId = alert.Id,
                TenantId = alert.TenantId,
                AlertRuleId = alertRule.Id,
                AlertTitle = alert.Title,
                AlertMessage = alert.Message,
                AlertLevel = alert.Level,
                TriggeredValue = alert.TriggeredValue,
                MetricName = alertRule.MetricName,
                Threshold = alertRule.Threshold,
                Operator = alertRule.Operator,
                AlertRuleName = alertRule.DisplayName,
                NotificationChannels = channels,
                TriggeredAt = alert.StartTime,
                Dimensions = alert.GetDimensions()
            };

            await _distributedEventBus.PublishAsync(alertEto);
        }

        private async Task SendThresholdWarningNotificationAsync(Alert alert)
        {
            try
            {
                var alertRule = await _alertRuleRepository.GetAsync(alert.AlertRuleId);

                // 只在告警持续时间较长时发送警告通知（避免过度通知）
                if (alert.Duration < 3600) // 小于1小时不发送警告
                {
                    return;
                }

                var notificationChannels = alertRule.GetNotificationChannels();
                if (notificationChannels == null || !notificationChannels.Contains("email"))
                {
                    return;
                }

                // 发布阈值警告事件
                await _distributedEventBus.PublishAsync(new ThresholdWarningEto
                {
                    AlertId = alert.Id,
                    TenantId = alert.TenantId,
                    AlertTitle = alert.Title,
                    CurrentValue = alert.TriggeredValue,
                    MetricName = alertRule.MetricName,
                    Threshold = alertRule.Threshold,
                    Duration = alert.Duration,
                    WarningAt = DateTime.Now
                });

                _logger.LogInformation("阈值警告通知已发送: {AlertTitle} - 持续时间: {Duration}秒",
                    alert.Title, alert.Duration);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送阈值警告通知失败: {AlertId}", alert.Id);
            }
        }
    }

    /// <summary>
    /// 活跃告警汇总
    /// </summary>
    internal class ActiveAlertsSummary
    {
        public int TotalCount { get; set; }
        public Dictionary<AlertLevel, int> AlertsByLevel { get; set; } = new();
        public Guid? TenantId { get; set; }
        public DateTime CreatedAt { get; set; }
    }
}